{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Routed Sequencing with Cleanup all Memory"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The previous model on Routed Sequencing with cleanup memory used a scalar ensemble to project only state 'A'. In this model, you will project all the states onto an ensemble of neurons as the state cycles through a five element sequence."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "# Setup the environment\n",
    "import matplotlib.pyplot as plt\n",
    "%matplotlib inline\n",
    "import numpy as np \n",
    "\n",
    "import nengo\n",
    "from nengo import spa             # import spa related packages\n",
    "from nengo.spa import Vocabulary"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Create the model"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "This model has parameters as described in the book. It extends the routed sequencing model by creating a scalar ensemble 'cleanup' and then projecting all the states on to this ensemble using a transformation matrix 'pd_new', specified by the vectors in the vocabulary. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "# Number of dimensions for the Semantic Pointers\n",
    "dimensions = 16\n",
    "\n",
    "# Make a model object with the SPA network\n",
    "model = spa.SPA(label='Routed_Sequence with cleanupAll', seed=7)\n",
    "\n",
    "with model:\n",
    "    # Specify the modules to be used\n",
    "    model.state = spa.State(dimensions=dimensions, feedback=1, feedback_synapse=0.01)\n",
    "    model.vision = spa.State(dimensions=dimensions) \n",
    "    # Specify the action mapping\n",
    "    actions = spa.Actions(\n",
    "        'dot(vision, START) --> state = vision',\n",
    "        'dot(state, A) --> state = B',\n",
    "        'dot(state, B) --> state = C',\n",
    "        'dot(state, C) --> state = D',\n",
    "        'dot(state, D) --> state = E',\n",
    "        'dot(state, E) --> state = A'\n",
    "    )\n",
    "    \n",
    "    # Creating the BG and Thalamus components that confirm to the specified rules\n",
    "    model.BG = spa.BasalGanglia(actions=actions)\n",
    "    model.thal = spa.Thalamus(model.BG)\n",
    "    \n",
    "    # Changing the seed of this RNG to change the vocabulary\n",
    "    rng = np.random.RandomState(7)\n",
    "    vocab = Vocabulary(dimensions=dimensions, rng=rng)\n",
    "    \n",
    "    # Creating the transformation matrix (pd_new) and cleanup ensemble (cleanup)  \n",
    "    vsize = len((model.get_output_vocab('state').keys))\n",
    "\n",
    "    pd = []\n",
    "    for item in range(vsize):\n",
    "        pd.append(model.get_output_vocab('state').keys[item])  \n",
    "          \n",
    "    pd_new = []\n",
    "    for element in range(vsize):\n",
    "        pd_new.append([vocab[pd[element]].v.tolist()]) \n",
    "        \n",
    "    # cleanup = nengo.Ensemble(300, dimensions=vsize)\n",
    "    model.cleanup = spa.State(neurons_per_dimension=300/vsize, dimensions=vsize)\n",
    "    \n",
    "    # Function that provides the model with an initial input semantic pointer.\n",
    "    def start(t):\n",
    "        if t < 0.4:\n",
    "            return '0.8*START+D'\n",
    "        else:\n",
    "            return '0'\n",
    "\n",
    "    # Input\n",
    "    model.input = spa.Input(vision=start)\n",
    "    \n",
    "    # Projecting the state on to the cleanup ensemble using a transformation matrix 'pd'.\n",
    "    for i in range(5):\n",
    "        nengo.Connection(model.state.output, model.cleanup.input[i], transform=pd_new[i])  "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Run the model"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "# Import the nengo_gui visualizer to run and visualize the model.\n",
    "from nengo_gui.ipython import IPythonViz\n",
    "IPythonViz(model, \"ch7-spa-sequence-routed-cleanup-all.py.cfg\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Press the play button in the visualizer to run the simulation. You should see the graphs as shown in the figure below.\n",
    "\n",
    "The graph in the middle shows the semantic pointer representation of the values stored in `state` and the graph on the bottom-right shows the response of the `cleanup` population. and the graph on the top-right shows the utility (similarity) of the current basal ganglia input (i.e., `state`) with the possible vocabulary vectors.  \n",
    "\n",
    "Since the cleanup operation is similar to a dot product between the state and the defined vocabulary vectors, the value of the `cleanup` population in a particular dimension rises only when the value of `state` (top-right graph) corresponds to that particular dimension. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "from IPython.display import Image\n",
    "Image(filename='ch7-spa-sequence-routed-cleanup-all.png')"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 2",
   "language": "python",
   "name": "python2"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 2
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython2",
   "version": "2.7.10"
  },
  "widgets": {
   "state": {},
   "version": "1.1.2"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 0
}
